package org.example.demo.module

import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.cookies.AcceptAllCookiesStorage
import io.ktor.client.plugins.cookies.HttpCookies
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

object HttpService {
    private const val TAG = "HttpService"

    val client = HttpClient(CIO) {
        install(HttpCookies) {
            storage = AcceptAllCookiesStorage()
        }
        install(ContentNegotiation) {
            json(Json {
                ignoreUnknownKeys = true
                coerceInputValues = true
            })
        }
        install(Logging) {
            level = LogLevel.ALL
            logger = object : Logger {
                override fun log(message: String) {
                    println("$TAG LOG: $message")
                }
            }
        }
    }

    suspend inline fun <reified T> post(
        url: String,
        header: Map<String, String>? = null,
        body: Any? = null
    ): T {
        val response = client.post(url) {
            headers.apply {
                header?.let {
                    it.forEach { (key, value) ->
                        append(key, value)
                    }
                }
            }
            setBody(body)
            contentType(ContentType.Application.Json)
        }
        return response.body<T>()
    }

    suspend inline fun <reified T> get(
        url: String,
        header: Map<String, String>? = null,
        param: Map<String, String>? = null
    ): T {
        val response = client.get(url) {
            headers.apply {
                header?.let {
                    it.forEach { (key, value) ->
                        append(key, value)
                    }
                }
            }
            url {
                parameters.apply {
                    param?.let {
                        it.forEach { (key, value) ->
                            append(key, value)
                        }
                    }
                }
            }
        }
        return response.body<T>()
    }
}
